#include <iostream>
#include <sstream>

#include "node.h"

using namespace std;

int getNode( int x, int y, int nx, int ny ) {
	return (x * nx) + ny;
}

int main() {
	srand( time(NULL) );
	vector<node> nodes;

	// start varable play-things

	int hypos = 2;

	long delay = 200000;
	bool sleep = false;
	bool echo  = true;

	int x = 20;
	int y = 20;

	// end varable play-things

	stringstream obuffer;

	bool loop = true;
	bool action;
	bool test = true;
	
	int iter_count = 0;
	int status;
	int best;
	int tmp;

	int node_count = x * y;

	for ( int i = 0; i < node_count; ++i ) {
		node temp_node( i, hypos ); // ID, Hypo Count
		nodes.push_back( temp_node );
	}


	for ( int ix = 0; ix < x; ++ix ) {
		for ( int iy = 0; iy < y; ++iy ) {

			nodes[getNode( x, y, ix, iy )].setStatus( rand() % hypos );
			//nodes[getNode( x, y, ix, iy )].setStatus( 0 );

			if ( ix != 0     ) { nodes[getNode( x, y, ix, iy )].linkNode( &nodes[getNode( x, y, ix - 1, iy )] ); } // Top
			if ( ix != x - 1 ) { nodes[getNode( x, y, ix, iy )].linkNode( &nodes[getNode( x, y, ix + 1, iy )] ); } // Bottom
			if ( iy != 0     ) { nodes[getNode( x, y, ix, iy )].linkNode( &nodes[getNode( x, y, ix, iy - 1 )] ); } // Left
			if ( iy != y - 1 ) { nodes[getNode( x, y, ix, iy )].linkNode( &nodes[getNode( x, y, ix, iy + 1 )] ); } // Right

		}
	}

	while ( loop ) {

//		cout << "Run " << iter_count << "\n";

		for ( int ix = 0; ix < x; ++ix ) {
			for ( int iy = 0; iy < y; ++iy ) {
				nodes[getNode( x, y, ix, iy )].resetRate();
			}
		}

		for ( int ix = 0; ix < x; ++ix ) {
			for ( int iy = 0; iy < y; ++iy ) {
				nodes[getNode( x, y, ix, iy )].rateNodes();
			}
		}

		action = false;

		for ( int ix = 0; ix < x; ++ix ) {
			for ( int iy = 0; iy < y; ++iy ) {
				tmp = nodes[getNode( x, y, ix, iy)].getStatus();

				obuffer << nodes[getNode( x, y, ix, iy )].getStatus();

				status = nodes[getNode( x, y, ix, iy )].getStatus();
				  best = nodes[getNode( x, y, ix, iy )].getBestStatus();

				if ( status != best ) {
					action = true;
					nodes[getNode( x, y, ix, iy )].setStatus( best );
					nodes[getNode( x, y, ix, iy)].rerateThings();
				}
				obuffer << " ";
			}
			obuffer << "\n";
		}
if ( echo ) {
		cout << obuffer.str();
		obuffer.str("");
		cout << "\n";
}
if ( sleep ) {
		usleep( delay );

}
	
		if ( ! action ) {
			test = true;
			for ( int ix = 0; ix < x; ++ix ) {
				for ( int iy = 0; iy < y; ++iy ) {
					if ( ! nodes[getNode(x, y, ix, iy )].strictCheck() ) {
						nodes[getNode(x, y, ix, iy )].setStatus( rand() % nodes[getNode(x, y, ix, iy )].getHypoCount() );
						test = false;
					}
				}
			}
			if ( test ) {
				loop = false;
			}
		}
		++iter_count;
	}
/*
	cout << "\n\n";

	for ( int ix = 0; ix < x; ++ix ) {
		for ( int iy = 0; iy < y; ++iy ) {

			tmp = nodes[getNode( x, y, ix, iy)].getStatus();

			if ( tmp == 0 ) { cout << "[31m"; }
			if ( tmp == 1 ) { cout << "[32m"; }
			if ( tmp == 2 ) { cout << "[33m"; }
			if ( tmp == 3 ) { cout << "[34m"; }

			cout << nodes[getNode( x, y, ix, iy )].getStatus() << " ";
		}
		cout << "\n";
	}
	cout << "[0m\n";

	cout << "Fin. It took " << iter_count << " Iterations to complete this graph.\n";
*/
}

